#include <cpp_primer.h>

using namespace std;

class StrVec {
public:
    StrVec() : elements(nullptr), first_free(nullptr), cap(nullptr) {  }
    StrVec(initializer_list<string>);
    StrVec(const StrVec&);
    StrVec& operator=(const StrVec&);
    ~StrVec();
    void push_back(const string&);
    size_t size() const { return first_free - elements;  }
    size_t capacity() const { return cap - elements;  }
    string *begin() const { return elements;  }
    string *end() const { return first_free;  }

    void reserve(const size_t new_cap);
    void resize(const size_t count);
    void resize(const size_t count, const string&);


private:
    allocator<string> alloc; // 分配元素

    // 被添加元素的函数使用
    void chk_n_alloc() { 
        if(size() == capacity())
            reallocate();
    }
    // 工具函数，被拷贝构造、赋值、析构使用
    pair<string*, string*> alloc_n_copy(const string*, const string*);
    void alloc_n_move(const size_t new_cap);
    void free();        //销毁元素，释放内存
    void reallocate();  // 获取更多内存，并拷贝现有元素

    string *elements;   // 指向数组首元素的指针
    string *first_free; // 指向数组第一个空闲元素的指针
    string *cap;        // 指向数组尾后的指针
};

void StrVec::push_back(const string &s)
{
    chk_n_alloc();
    alloc.construct(first_free++, s);
}

pair<string*, string*> StrVec::alloc_n_copy(const string *b, const string *e)
{
    // 申请空间，返回首指针
    auto data = alloc.allocate(e - b);
    // 返回一个pair类型，花括号用来初始化。c++11引入的返回值优化
    return {data, uninitialized_copy(b, e, data)};
}

void StrVec::free()
{
    if(elements) {
        // 逆序销毁
        for(auto p = first_free; p != elements;)
            alloc.destroy(--p);
        alloc.deallocate(elements, cap - elements);
    }
}

StrVec::StrVec(const StrVec &s)
{
    auto newdata = alloc_n_copy(s.begin(), s.end());
    elements = newdata.first;
    first_free = cap = newdata.second;
}

StrVec::~StrVec()
{
    free();
}

StrVec& StrVec::operator=(const StrVec &rhs)
{
    auto data = alloc_n_copy(rhs.begin(), rhs.end());
    free();
    elements = data.first;
    first_free = cap = data.second;
    return *this;
}

void StrVec::alloc_n_move(const size_t new_cap)
{
    auto newdata = alloc.allocate(new_cap);
    auto dest = newdata;    // 指向新数组中的下一个空闲位置
    auto elem = elements;   // 指向旧数组中的下一个元素
    for(size_t i = 0; i != size(); ++i) 
        alloc.construct(dest++, move(*elem++));
    free();
    elements = newdata;
    first_free = dest;
    cap = elements + new_cap;
}

void StrVec::reallocate()
{   
    // 分配当前大小两倍的内存空间
    auto newcapacity = size() ? 2 * size() : 1;
    alloc_n_move(newcapacity); 
}

void StrVec::reserve(const size_t new_cap)
{
    if(new_cap <= capacity()) 
        return;
    alloc_n_move(new_cap);
}

void StrVec::resize(const size_t count)
{
    resize(count, string());
}

void StrVec::resize(const size_t count, const string &s)
{
    if(count > size()) {
        if(count > capacity())
            reserve(count * 2);
        for(size_t i = size(); i != count; ++i)
            alloc.construct(first_free++, s);
    }
    else if(count < size()) {
        while(first_free != elements + count)
            alloc.destroy(--first_free);
    }
}

StrVec::StrVec(initializer_list<string> il)
{
    auto newdata = alloc_n_copy(il.begin(), il.end());
    elements = newdata.first;
    first_free = cap = newdata.second;
}

int main()
{

    return 0;
}
